Métodos


    Podemos olhar métodos por dois ângulos em POO.


    O primeiro, computacional, é que métodos são o equivalente em POO de funções. E, portanto, obedecem as mesmas regras:


    Precisam ter um nome, um conjunto de parâmetros (que pode ser vazio) e um tipo de retorno (que pode ser nenhum).


    Para criar um método em JAVA usamos o padrão: <tipo_de_retorno> <nome> (<parametros>) {<corpo>}


    Observe que em métodos com retorno void (ou seja, sem retorno) a palavra return não pode aparecer, enquanto em métodos com qualquer tipo de retorno que não seja void é obrigatório que ela apareça para indicar o resultado da excecução do método.


    A segunda forma de ver métodos em POO, e que se combina com a forma anterior, é como comportamentos de uma entidade.


    Métodos só existem dentro de classes, portanto, devem ser algum comportamento que a entidade que a classe representa tem na vida real, ou algum comportamento sistêmico da classe. Isso restringe o que vimos anteriormente, funções são globais, portanto podem manipular quaisquer valores no código, já métodos estão reservados ao escopos de suas classes então devem manipular apenas o que estiver diretamente relacionado à sua classe.


    Por fim, lembre-se que podemos ter quantos métodos quisermos em um classe. Até mesmo métodos de mesmo nome, isso se chama sobrecarga de operadores, no entanto, é obrigatório que eles tenham assinaturas diferentes! Assinatura é o nome do método + seu conjunto de parâmetros.


Construtor


    Dissemos que para construir qualquer objeto precisamos dizer new + nomedaclasse + ();


    Já vimos em métodos que para invocar um método usamos nome().


    Então quando criamos um objeto estamos invocando um método de mesmo nome que a classe. Mas onde está esse método?


        public class Pessoa{

                public String nome;

        }


    A classe pessoa não tem um método com assinatura Pessoa() então de onde ele vem?


    O JAVA assume por padrão que, se você escreveu uma classe, você quer construir objetos a partir daquela classe.


    Por isso, o compilador adiciona um método construtor em todas as classes que não tiverem construtores.


    Vamos rescrever a classe Pessoa, dessa vez faremos explicitamente o que o JAVA fez:


        public class Pessoa{

                public String nome;


                public Pessoa() { }

        }


    Observe algumas peculiaridades sobre esse método.


    A mais importante é que ele não tem tipo de retorno (nem void) isso se dá porque ele sempre retornará a instância da classe (objeto), portanto, ele não pode retornar outros valores ou deixar de retornar.


    Outra peculiaridade é que, apesar de não marcarmos os construtores como estáticos, eles estão sempre disponíveis na memória, podendo ser invocados a partir de qualquer classe onde a classe a ser instânciada esteja visível. Diferente dos demais métodos de uma classe que, ou são dependentes de um objeto e só estão disponíveis enquanto o objeto estiver na memória, ou são estáticos e estão disponíveis por meio da classe.


    Você pode aplicar sobrecarga nos construtores também da mesma forma que os métodos comuns, lembre-se apenas que o construtor padrão, vazio, só é crido pelo JAVA se não houver mais nenhum construtor na classe. Então se você fizer um construtor com parâmetros, aquele construtor sem parâmetros "automático" deixa de existir, então você precisará escrevê-lo também se quiser usá-lo.


    Veja os exemplos:


        public class Pessoa{

                public String nome;

        }


    Pessoa possui um construtor de assinatura Pessoa() criado pelo compilador.


        public class Pessoa{

                public String nome;


                        public Pessoa(String nome) {this.nome = nome;}

        }


    Pessoa, acima, possui um construtor de assinatura Pessoa(String) apenas. O automático não será criado. Observer que agora Pessoa só pode ser instanciada se passarmos um nome.


        public class Pessoa{

                public String nome;


                public Pessoa(){}

                public Pessoa(String nome) {this.nome = nome;}

        }


    Pessoa acima tem um construtor de assinatura Pessoa(String) e um de assinatura Pessoa().


    Um não faz nada de especial além de criar o objeto, o outro espera uma String para atribuir em nome;


    Uma última consideração, de dentro da própria classe podemos invocar um construtor em outro método.


    Para isso não usamos o new, porque não queremos criar um objeto, e não chamamos o construtor pelo nome da classe, mas por this().


    Quando fazemos isso o construtor se comportará como um método comum de retorno void, rodará sua lógica normalmente sem criar um novo objeto.


    Podemos também usar um construtor para invocar outro dessa forma.


    Veja os exemplos:


        public class Pessoa{


                public String nome;


                public Pessoa(){

                        this("anônimo");

                }


                public Pessoa(String nome) {

                        this.nome = nome;

                }

        }


    No caso acima, o construtor que o pogramador espera que seja usado é o de assinatura Pessoa(String), que cria uma pessoa com um nome.


    No entanto exite um construtor que permite não passar um nome de assinatura Pessoa().


    Se ele for invocado, ele invocará o outro construtor (Pessoa(String)), passando como nome o valor padrão "anônimo".


    Ele é capaz de invocar o outro construtor usando this().


Encapsulamento


    Até agora vimos atributos e métodos públicos. Também vimos, na lição de objetos que temos que ter uma classe Programa, com um método main, para podermos criar nossos objetos. Na POO, o cenário mais comum é usar objetos fora da sua própria classe, salvo raras exceções. Quando usamos atributos e métodos públicos dizemos que eles tem visibilidade fora de sua classe. Ou seja, qualquer outra classe do programa pode usá-los. Podemos querer restringir esse comportamento. Pode haver partes de nossa classe que não queremos expor para outras classes. Para isso usamos o encapsulamento.


    public - Torna o membro (atributo ou método) visível para qualquer classe no programa. protected - Torna o membro visível apenas às classes do próprio pacote e classes-filhas (que podem estar em outro pacote). package-private - Quando não colocamos nenhum modificador o membro é visíveis apenas às classes do pacote (padrão). private - Torna o membro visível apenas de dentro da própria classe.


Métodos Acesso


    O padrão JAVA é com todos os atributos private, mas como acessá-los uma vez que estão privados? Lembre-se do conceito de private: visibilidade apenas dentro da classe. Isso quer dizer que qualquer membro da classe continua sendo capaz de ler e escrever nesses atributos.


    É aí que entram os métodos de acesso. Podemos fazer dois métodos para cada atributo, uma para retornar o valor e outro para setar um novo valor. Assim poderemos voltar a manipular nossos atributos de fora da classe, mas com maior controle.


    Para começar segue a estrutura dos métodos de acesso:


    GET:


            public <tipo_do_atributo> get<nome_do_atributo>( ) { return this.<nome_do_atributo>; }


    SET:


            public void set<nome_do_atributo>(<tipo_do_atributo> <nome_do_parametro>) { this.<nome_do_atributo> = <nome_do_parametro>; }


    Vamos criar métodos de acesso na classe Pessoa:


        public class Pessoa{

                private String nome;

                private int idade;


                public String getNome() { return this.nome; }

                public int getIdade(){ return this.idade; }


                public void setNome(String nome){ this.nome = nome; }

                public void setIdade(int idade){ this.idade = idade; }

        }


    Com os métodos de acesso, temos mais controle dos atributos, pois quando usamos atributos públicos e uma mudança é feita nós nem sabemos. Já com os métodos de acesso, rodamos um trecho do código toda vez que o atributo é lido ou escrito e nele podemos fazer o que quisermos, como validações.